package com.weifly.weistock.core.task;

import com.weifly.weistock.core.market.StockPriceDto;
import com.weifly.weistock.core.market.impl.SinaStockMarketService;
import com.weifly.weistock.core.market.StockMarketService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Calendar;

/**
 * 更新服务
 *
 * 周六、周日，休眠1
 * 09:00:00前、15:05:00后，休眠2
 * 09:00:00后、15:05:00前，判断，在09:18:00时，执行判断
 * 09:00:00后、15:05:00前，运行或休眠1
 *
 * 08:50:00前、15:05:00后，每10分钟执行一次
 * 08:50:00后、15:05:00前，初始化、休眠2、判断状态下，每1分钟执行一次。
 *                          运行状态下，每3秒执行一次。
 *                          休眠1状态下，每10分钟执行一次。
 *
 * @author weifly
 * @since 2019/2/3
 */
public class AbstractUpdateService {

    private Logger logger = LoggerFactory.getLogger(AbstractUpdateService.class);

    public static final int STATUS_INIT = 1; // 初始化，一定执行一次
    public static final int STATUS_SLEEP1 = 2; // 休眠1，非交易日，每10分钟执行一次
    public static final int STATUS_SLEEP2 = 3; // 休眠2，非交易时间，每10分钟执行一次
    public static final int STATUS_CHECK = 4; // 判断，每分钟执行一次
    public static final int STATUS_RUN = 5; // 运行，每3秒执行一次

    private static final int TIME_8HOUR_50MINUTE = 8*3600*1000 + 50*60*1000; // 08:50:00
    private static final int TIME_9HOUR = 9*3600*1000;                          // 09:00:00
    private static final int TIME_9HOUR_17MINUTE = 9*3600*1000 + 17*60*1000; // 09:17:00
    private static final int TIME_9HOUR_23MINUTE = 9*3600*1000 + 23*60*1000; // 09:23:00
    private static final int TIME_9HOUR_32MINUTE = 9*3600*1000 + 32*60*1000; // 09:32:00
    private static final int TIME_14HOUR_58MINUTE = 14*3600*1000 + 58*60*1000; // 14:58:00
    private static final int TIME_15HOUR_5MINUTE = 15*3600*1000 + 5*60*1000; // 15:05:00

    private long SLEEP_TIME_10_MINUTE = 600 * 1000;
    private long SLEEP_TIME_1_MINUTE = 60 * 1000;
    private long SLEEP_TIME_3_SECOND = 3 * 1000;

    private UpdateStatus status = new UpdateStatus(); // 运行状态
    private Calendar calendar = Calendar.getInstance();
    private StockMarketService stockMarketService = new SinaStockMarketService();

    /**
     * 重置为初始化状态
     */
    protected void resetStatus(){
        this.status.setStatus(STATUS_INIT);
    }

    /**
     * 检查运行状态
     *
     * @return
     */
    protected UpdateStatus checkStatus(){
        UpdateStatus status = this.checkStatusInner();

        UpdateStatus copy = new UpdateStatus();
        copy.setStatus(status.getStatus());
        copy.setSleepTime(status.getSleepTime());
        copy.setPreStatus(status.getPreStatus());
        copy.setCheckYear(status.getCheckYear());
        copy.setCheckMonth(status.getCheckMonth());
        copy.setCheckDay(status.getCheckDay());
        copy.setCheckHour(status.getCheckHour());
        copy.setCheckMinute(status.getCheckMinute());
        copy.setCheckSecond(status.getCheckSecond());
        return copy;
    }


    protected UpdateStatus checkStatusInner(){
        this.updateCheckTime();
        this.status.setPreStatus(this.status.getStatus());

        // 工作日判断，周六、周日非交易日
        int dayOfWeek = this.status.getCheckWeek();
        if(dayOfWeek!=Calendar.MONDAY && dayOfWeek!=Calendar.TUESDAY && dayOfWeek!=Calendar.WEDNESDAY && dayOfWeek!=Calendar.THURSDAY && dayOfWeek!=Calendar.FRIDAY){
            this.status.setStatus(STATUS_SLEEP1);
            this.status.setSleepTime(this.SLEEP_TIME_10_MINUTE);
            return this.status;
        }

        int todayTime = this.status.getCheckHour()*3600000 + this.status.getCheckMinute()*60000 + this.status.getCheckSecond()*1000;

        // 交易时间判断，9点前、15点05后不交易
        if(todayTime<=TIME_9HOUR || todayTime>=TIME_15HOUR_5MINUTE){
            this.status.setStatus(STATUS_SLEEP2);
            if(TIME_8HOUR_50MINUTE<todayTime && todayTime<=TIME_9HOUR){
                this.status.setSleepTime(SLEEP_TIME_1_MINUTE);
            }else{
                this.status.setSleepTime(SLEEP_TIME_10_MINUTE);
            }
            return this.status;
        }

        // 根据状态判断
        int statusInt = this.status.getStatus();
        if(statusInt==STATUS_SLEEP1){
            // 已经判断为非交易日，不做处理
            return this.status;
        }else if(statusInt==STATUS_RUN){
            // 已判断为交易日，不做处理
            return status;
        }else if(statusInt==STATUS_INIT || statusInt==STATUS_SLEEP2 || statusInt==STATUS_CHECK){
            StockPriceDto stockPrice = this.stockMarketService.getStockPrice("510050");
            if(stockPrice==null || stockPrice.getPriceDate()==null || stockPrice.getPriceDate().isEmpty()){
                throw new RuntimeException("无法获得510050的价格信息，无法判断今天是否开盘");
            }
            String[] priceDateFields = stockPrice.getPriceDate().split("-");
            int priceDateYear = Integer.parseInt(priceDateFields[0]);
            int priceDateMonth = Integer.parseInt(priceDateFields[1]);
            int priceDateDay = Integer.parseInt(priceDateFields[2]);
            if(this.status.getCheckYear()==priceDateYear && this.status.getCheckMonth()==priceDateMonth && this.status.getCheckDay()==priceDateDay){
                // 今天有报价，开盘
                this.status.setStatus(STATUS_RUN);
                this.status.setSleepTime(this.SLEEP_TIME_3_SECOND);
            }else{
                // 今天没有报价
                if((TIME_9HOUR_17MINUTE<todayTime && todayTime<TIME_9HOUR_23MINUTE) || (TIME_9HOUR_32MINUTE<todayTime && todayTime<TIME_14HOUR_58MINUTE)){
                    // 在开盘时间没有报价，今天不开盘
                    this.status.setStatus(STATUS_SLEEP1);
                    this.status.setSleepTime(SLEEP_TIME_10_MINUTE);
                }else{
                    // 继续判断
                    this.status.setStatus(STATUS_CHECK);
                    this.status.setSleepTime(SLEEP_TIME_1_MINUTE);
                }
            }
            return this.status;
        }else{
            throw new RuntimeException("不支持的状态：" + this.status);
        }
    }

    private void updateCheckTime(){
        this.calendar.setTimeInMillis(System.currentTimeMillis());
        this.status.setCheckYear(this.calendar.get(Calendar.YEAR));
        this.status.setCheckMonth(this.calendar.get(Calendar.MONTH)+1);
        this.status.setCheckDay(this.calendar.get(Calendar.DAY_OF_MONTH));
        this.status.setCheckWeek(this.calendar.get(Calendar.DAY_OF_WEEK));
        this.status.setCheckHour(this.calendar.get(Calendar.HOUR_OF_DAY));
        this.status.setCheckMinute(this.calendar.get(Calendar.MINUTE));
        this.status.setCheckSecond(this.calendar.get(Calendar.SECOND));
    }

    public static String getStatusName(int statusInt){
        if(statusInt==STATUS_INIT){
            return "初始化";
        }else if(statusInt==STATUS_SLEEP1){
            return "休眠 非交易日";
        }else if(statusInt==STATUS_SLEEP2){
            return "休眠 非交易时间";
        }else if(statusInt==STATUS_CHECK){
            return "判断";
        }else if(statusInt==STATUS_RUN){
            return "运行";
        }else{
            return "未知";
        }
    }
}
